package result

import (
	"context"
	"encoding/json"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/rest/httpx"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/grpc/status"
	"hrt/internal/common/errorx"
	"hrt/internal/common/xerr"
	"net/http"
)

func GetTraceId(ctx context.Context) string {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasTraceID() {
		return spanCtx.TraceID().String()
	}
	return ""
}

type ResponseSuccessBean struct {
	Code    uint32      `json:"code"`
	Msg     string      `json:"msg"`
	Data    interface{} `json:"data"`
	TraceId string      `json:"traceId"`
}
type NullJson struct{}

func Success(data interface{}, ctx context.Context) *ResponseSuccessBean {
	return &ResponseSuccessBean{200, "OK", data, GetTraceId(ctx)}
}

type ResponseErrorBean struct {
	Code    uint32 `json:"code"`
	Msg     string `json:"msg"`
	TraceId string `json:"traceId"`
}

func Error(errCode uint32, errMsg string, ctx context.Context) *ResponseErrorBean {
	traceId := GetTraceId(ctx)
	return &ResponseErrorBean{errCode, errMsg, traceId}
}

func HttpResult(r *http.Request, w http.ResponseWriter, resp interface{}, err error) {

	if err == nil {

		toString, _ := json.Marshal(resp)
		logx.WithContext(r.Context()).Info(map[string]interface{}{
			"msg":  "最终返回",
			"resp": string(toString),
		})

		//成功返回
		r := Success(resp, r.Context())
		httpx.WriteJson(w, http.StatusOK, r)
	} else {
		//错误返回
		errcode := errorx.DefaultCode
		errmsg := "服务器开小差啦，稍后再来试一试"

		causeErr := errors.Cause(err)                  // err类型
		if e, ok := causeErr.(*errorx.CodeError); ok { //自定义错误类型
			//自定义CodeError
			errcode = e.Code
			errmsg = e.Msg
		} else {
			if gstatus, ok := status.FromError(causeErr); ok { // grpc err错误
				grpcCode := uint32(gstatus.Code())
				if xerr.IsCodeErr(grpcCode) { //区分自定义错误跟系统底层、db等错误，底层、db错误不能返回给前端
					errcode = int(grpcCode)
					errmsg = gstatus.Message()
				}
			}
		}

		logx.WithContext(r.Context()).Errorf("【API-ERR】 : %+v ", err)
		httpx.WriteJson(w, http.StatusOK, Error(uint32(errcode), errmsg, r.Context()))
	}
}
